
package com.leyuangame.core.websocket.handler;

import com.alibaba.fastjson.JSON;
import com.leyuangame.core.BMDataContext;
import com.leyuangame.core.enums.PlayUserLogType;
import com.leyuangame.core.enums.WsClientCommand;
import com.leyuangame.core.websocket.GameServer;
import com.leyuangame.core.websocket.client.NettyClients;
import com.leyuangame.dao.repository.jpa.PlayUserLogRepository;
import com.leyuangame.dao.repository.jpa.PlayUserRepository;
import com.leyuangame.dao.repository.jpa.user.PlayUser;
import com.leyuangame.dao.repository.jpa.user.PlayUserLog;
import com.leyuangame.redis.JedisClient;
import com.leyuangame.utils.UKTools;
import org.apache.commons.lang.StringUtils;
import org.hibernate.engine.internal.CacheHelper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.tio.core.Aio;
import org.tio.core.ChannelContext;
import org.tio.core.maintain.Groups;
import org.tio.core.maintain.Ids;
import org.tio.http.common.HttpRequest;
import org.tio.http.common.HttpResponse;
import org.tio.websocket.common.WsRequest;
import org.tio.websocket.server.handler.IWsMsgHandler;

import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.*;
import java.util.concurrent.locks.ReentrantReadWriteLock;

@Component
public class GameEventHandler implements IWsMsgHandler
{
	protected GameServer server;
	@Autowired
	private PlayUserLogRepository playUserLogRepository;
	@Autowired
	private PlayUserRepository playUserRepository;
    @Autowired
    private JedisClient jedisClient;
    @Autowired
    private BMDataContext bmDataContext;
//    @Value("${leyuancard.redis.match.perfix}")
//    private String userMatchPerfix;
//
//    @Value("${leyuancard.redis.gamematch.perfix}")
//    private String gameMatchPerfix;
    public PlayUserLogRepository getPlayUserLogRepository() {
        return playUserLogRepository;
    }

    public void setPlayUserLogRepository(PlayUserLogRepository playUserLogRepository) {
        this.playUserLogRepository = playUserLogRepository;
    }

    public PlayUserRepository getPlayUserRepository() {
        return playUserRepository;
    }

    public void setPlayUserRepository(PlayUserRepository playUserRepository) {
        this.playUserRepository = playUserRepository;
    }

    /**
	 * 握手时走这个方法，业务可以在这里获取cookie，request参数等
	 */
	@Override
	public HttpResponse handshake(HttpRequest request, HttpResponse httpResponse, ChannelContext channelContext) throws Exception {
		String token = request.getParam("token");
		String orgi = request.getParam("orgi") ;
		if(!StringUtils.isBlank(token)&&!StringUtils.isBlank(orgi)) {
			channelContext.setAttribute(token, token);
            //绑定用户ID
            PlayUser user = playUserRepository.findPlayUserByToken(token);
            Aio.bindUser(channelContext, user.getId());
            Aio.bindToken(channelContext, user.getToken());
			BeiMiClient client = new BeiMiClient();
			client.setTime(new Date().getTime());
			client.setToken(token);
			client.setOrgi(orgi);
            client.setServer(this.server);
            client.setChannelContext(channelContext);
			//记录用户登陆信息
            String clientIp = request.getClientIp();
			playUserLogRepository.saveAndFlush(new PlayUserLog(user.getId(), PlayUserLogType.用户登陆.toString(),clientIp+"在"+orgi+"设备登陆"));
			NettyClients.getInstance().getSystemClientsMap().put(user.getId(),client);
		}else {
			Aio.remove(channelContext, "业务层不同意握手");
		}
		return httpResponse;
	}

	/**
	 * 字节消息（binaryType = arraybuffer）过来后会走这个方法
	 */
	@Override
	public Object onBytes(WsRequest wsRequest, byte[] bytes, ChannelContext channelContext) throws Exception {
		channelContext.getClientNode().getIp();
		ByteBuffer buffer = ByteBuffer.allocate(1);
		return buffer;
	}
	
	/**
	 * 字符消息（binaryType = blob）过来后会走这个方法
	 */
	@Override
	public Object onText(WsRequest wsRequest, String text, ChannelContext channelContext) throws Exception {
        if(text!=null) {
			BeiMiClient beiMiClient = JSON.parseObject(text , BeiMiClient.class) ;
            beiMiClient.setServer(this.server);
            beiMiClient.setChannelContext(channelContext);
			//更新用户信息
			if(beiMiClient.getCommand()!=0) {
                NettyClients.getInstance().getSystemClientsMap().put(beiMiClient.getToken(),beiMiClient);
				switch(beiMiClient.getCommand()) {
					//加入房间
				    case 1001:
				        channelContext.setAttribute("partionid",beiMiClient.getPartition());
				        NettyClients.getInstance().joinRoom(channelContext,beiMiClient.getToken(),beiMiClient.getRoom(),beiMiClient.getPartition());
						break;
                    //离开房间
                    case 1002:
                        channelContext.setAttribute("partionid","");
                        NettyClients.getInstance().leaveRoom(channelContext,beiMiClient.getToken(),beiMiClient.getRoom(),beiMiClient.getPartition());
                        break;
                    //开始匹配
                    case 1003:
                        channelContext.setAttribute("partionid",beiMiClient.getPartition());
                        NettyClients.getInstance().beginMatch(channelContext,beiMiClient.getToken(),beiMiClient.getPartition());
                        break;
                    case 1004:
                        NettyClients.getInstance().ready(channelContext,beiMiClient);
                        break;
                        //this.match(beiMiClient);
//					case "docatch":this.onCatch(beiMiClient); break;
//					case "giveup":this.onGiveup(beiMiClient); break;
//					case "cardtips":this.onCardTips(beiMiClient); break;
//					case "doplaycards":this.onPlayCards(beiMiClient); break;
//					case "nocards":this.onNoCards(beiMiClient); break;
//					case "selectcolor":this.onSelectColor(beiMiClient); break;
//					case "selectaction":this.onActionEvent(beiMiClient); break;
//					case "restart":this.onRestart(beiMiClient); break;
//					case "start":this.onStart(beiMiClient); break;
//					case "recovery":this.onRecovery(beiMiClient); break;
//					case "leave":this.onLeave(beiMiClient); break;
//					case "command":this.onCommand(beiMiClient); break;
//					case "searchroom":this.onSearchRoom(beiMiClient); break;
//					case "message":this.onMessage(beiMiClient); break;

					//zjh
					
				}
			}
		}
		return null;
	}
	/**
	 * 当客户端发close flag时，会走这个方法
	 */
	@Override
	public Object onClose(WsRequest wsRequest, byte[] bytes, ChannelContext channelContext) throws Exception {
		Aio.remove(channelContext, "receive close flag");
        NettyClients.getInstance().getSystemClientsMap().remove(channelContext.getToken());//移除用户
        Object tmp_partion = channelContext.getAttribute("partionid");
        String partionid = tmp_partion==null?"":(String)tmp_partion;

        Object tmp_roomid = channelContext.getAttribute("roomid");
        String roomid = tmp_roomid==null?"":(String)tmp_roomid;

        RoomInfo roomInfo = null;
        if(!partionid.equals("")){//若在分区内 移除用户
            roomInfo = NettyClients.getInstance().getGroupRoomClients().get(roomid);
            if(roomInfo==null){
                TreeSet<RoomInfo> roomInfos = NettyClients.getInstance().getWaitRoom().get(partionid);
                Iterator<RoomInfo> iterator = roomInfos.iterator();
                while (iterator.hasNext()){
                    final RoomInfo next = iterator.next();
                    if(next.getRoom_id().equals(roomid)){
                        roomInfo = next;
                    }
                }
            }
            Iterator<BeiMiClient> it = roomInfo.players.iterator();
            while (it.hasNext()){
                BeiMiClient next1 = it.next();
                if(next1.getToken().equals(channelContext.getToken())){
                    //TODO 告诉房间人员变更信息
                    it.remove();
                    NettyClients.getInstance().sendRoomInfo(channelContext,roomid,roomInfo);
                }
            }
        }
		return null;
	}

	public GameServer getServer() {
		return server;
	}

	public void setServer(GameServer server) {
		this.server = server;
	}

    /**
     * 玩家点击开始匹配进入匹配机制
     * @param beiMiClient
     */
	public void match(BeiMiClient beiMiClient){
        PlayUser user = playUserRepository.findPlayUserByToken(beiMiClient.getToken());
        if(user==null)
            return;
	    //在redis设置一个key 并表示玩家进入匹配状态
        jedisClient.set(bmDataContext.userMatchPerfix+beiMiClient.getUserid(),"1");
        //将玩家加入到匹配队列
        //simple GAME:MATCH:DOUDIZHU:PARTIONID
        jedisClient.sadd(bmDataContext.gameMatchPerfix+beiMiClient.getPlayway()+":"+beiMiClient.getPartition(),user.getId());
    }
}  